<?php

namespace App\Service\Cruise\Mission;

use App\Enums\BaseErrorCode;
use App\Events\Cruise\CruiseOrderChangeEvent;
use App\Exceptions\Custom\ResponseHttpException;
use App\Library\Rms\RmsCurl;
use App\Library\Rms\RmsUserApi;
use App\Models\Activity\ActivityActionModel;
use App\Models\Activity\ActivityModel;
use App\Models\Activity\ActivityShopJoinModel;
use App\Models\Cruise\CruiseOrderInputModel;
use App\Models\Cruise\CruiseOrderModel;
use App\Models\Cruise\CruiseOrderProcessV2Model;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\Kms\User\KmsUser;
use App\Models\Shop\ShopModel;
use App\Models\System\SystemNotifyCenterModel;
use App\Service\BaseService;
use App\Service\Common\SmsService;
use App\Service\System\SystemNotifyService;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Kuafu\GeneralFs\BuildFs;
use Ritaswc\LarkCardMessageBuilder\CardMessageBuilder;
use Ritaswc\LarkCardMessageBuilder\Tag;

class ActivityInputService extends CruiseOrderInputBaseService
{
    public ?CruiseOrderModel  $cruiseOrderModel;
    private ?CruiseOrderModel $oldCruiseOrderModel;
    private int               $userId;

    public function __construct(int $cruiseOrderId, int $userId = 0)
    {
        $this->userId = $userId;

        $this->cruiseOrderModel = CruiseOrderModel::query()->where('id', $cruiseOrderId)->first();
        if (!$this->cruiseOrderModel) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null,
                "不存在的稽核任务ID:{$cruiseOrderId}");
        }

        $this->oldCruiseOrderModel = clone $this->cruiseOrderModel;

        $this->templateType = CruiseTemplateModel::TYPE_9;
        $this->sysTemplate  = CruiseTemplateModel::SYS_TEMPLATE_ACTIVITY_ACTION;

        parent::__construct($cruiseOrderId, $this->cruiseOrderModel->type,
            CruiseTemplateModel::SYS_TEMPLATE_ACTIVITY_ACTION, $this->cruiseOrderModel);
    }

    /**
     * 初始化订单
     * @param int $shopId
     * @param int $userId
     * @param int $templateId
     * @return self
     */
    public static function initOrder(int $shopId, int $userId, int $templateId): self
    {
        //添加订单表
        $cruiseOrder                       = new CruiseOrderModel();
        $cruiseOrder->orderNo              = '';
        $cruiseOrder->shopId               = $shopId;
        $cruiseOrder->type                 = CruiseTemplateModel::TYPE_9;
        $cruiseOrder->status               = CruiseOrderModel::STATUS_NOT_SUBMIT;
        $cruiseOrder->handlerId            = $userId;
        $cruiseOrder->templateId           = $templateId;
        $cruiseOrder->cruiseCheckCompanyId = '';
        $cruiseOrder->save();

        $obj = (new self($cruiseOrder->id, $userId));

        $obj->initOrderInput(false, $templateId);

        // cruise_order_change事件
        event(new CruiseOrderChangeEvent($cruiseOrder->id, CruiseTemplateModel::TYPE_9, null, $cruiseOrder));

        return $obj;
    }

    /**
     * 获取享元
     * @param int $cruiseOrderId
     * @param int $userId
     * @return self
     */
    public static function getSingleton(int $cruiseOrderId, int $userId = 0): self
    {
        return Cache::store('array')->remember("ActivityInputService:{$cruiseOrderId}:{$userId}", 120,
            function () use ($cruiseOrderId, $userId) {
                return new self($cruiseOrderId, $userId);
            });
    }

    /**
     * 初始化表单信息
     * @param bool $forceUpdate
     * @param int $templateId
     * @return void
     */
    public function initOrderInput(bool $forceUpdate = false, int $templateId = 0): void
    {
        if (!$templateId) {
            $templateId = CruiseTemplateModel::query()
                                             ->where('type', $this->templateType)
                                             ->where('sysTemplate', $this->sysTemplate)
                                             ->where('status', CruiseTemplateModel::STATUS_ON)
                                             ->value('id') ?? 0;
            if (!$templateId) {
                throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null,
                    "获取模板类型对应模板失败:{$this->templateType}");
            }
        }

        // 幂等-不再创建
        if (!$forceUpdate && CruiseOrderInputModel::query()->where('orderId', $this->orderId)
                                                  ->where('templateType', $this->templateType)->count()) {
            return;
        }

        parent::baseInitOrderInput($templateId);
    }

    public function getInputObjectFill(): array
    {
        $submit = true; // 提交权限；

        $data = parent::baseGetInputObjectFill(!$submit);
        $data['submit'] = $submit;

        return $data;
    }

    public function saveUserContentJson(string $field, $value, array $auditValue = []): void
    {
        // 状态校验
        if (!in_array($this->cruiseOrderModel->status,
            [CruiseOrderModel::STATUS_NOT_SUBMIT, CruiseOrderModel::STATUS_NOT_MODIFY])) {
            $statusText = CruiseOrderModel::CRUISE_STATUS_MAPPING[$this->cruiseOrderModel->status] ?? '';
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "当前状态: {$statusText}，不允许修改");
        }

        // 角色校验
//        $handler = $this->getCurrentHandlerInfo($this->cruiseOrderModel->status);
//        if (!in_array($this->userId, $handler['userIds'] ?? [])) {
//            $userNames = $handler['userNames'] ?? '';
//            BaseService::throwErr("您无权操作，当前处理人：{$userNames}");
//        }

        parent::baseSaveUserContentJson($field, $value, $auditValue);
    }

    public function submitOrder(): void
    {
        // 状态校验
        if (!in_array($this->cruiseOrderModel->status,
            [CruiseOrderModel::STATUS_NOT_SUBMIT, CruiseOrderModel::STATUS_NOT_MODIFY])) {
            $statusText = CruiseOrderModel::CRUISE_STATUS_MAPPING[$this->cruiseOrderModel->status] ?? '';
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "当前状态: {$statusText}，不允许提交");
        }

        // 角色校验
//        $handler = $this->getCurrentHandlerInfo($this->cruiseOrderModel->status);
//        if (!in_array($this->userId, $handler['userIds'])) {
//            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null,
//                "您无权操作，当前处理人：{$handler['userNames']}");
//        }

        list($activity, $activityAction, $join) = $this->getActivityAndAction();

        // 判断其他action是否已经提交
        $finish = ActivityShopJoinModel
            ::query()
            ->where('activityId', $activity->id)
            ->where('shopId', $this->cruiseOrderModel->shopId)
            ->whereIn('actionType', [ActivityActionModel::ACTION_TYPE_1, ActivityActionModel::ACTION_TYPE_3])
            ->where('status', ActivityShopJoinModel::STATUS_3)
            ->count();
        if ($finish) {
            BaseService::throwErr("活动已完成，无需提交");
        }

        $finish2 = ActivityShopJoinModel
            ::query()
            ->where('activityId', $activity->id)
            ->where('shopId', $this->cruiseOrderModel->shopId)
            ->whereIn('actionType', [ActivityActionModel::ACTION_TYPE_2])
            ->whereIn('status', [ActivityShopJoinModel::STATUS_3, ActivityShopJoinModel::STATUS_1])
            ->count();
        if ($finish2) {
            BaseService::throwErr("已有其他活动提交，无法提交");
        }

        parent::baseSubmitOrder(true);

        DB::beginTransaction();

        // 总部审核
        $this->cruiseOrderModel->status = CruiseOrderModel::STATUS_NOT_REVIEW;
        $this->cruiseOrderModel->save();

        // 操作日志
        $inputs  = $this->getInputObjectFill();
        $details = [];
        foreach ($inputs['lists'] as $positions) {
            foreach ($positions['projects'] as $project) {

                if (is_array($project["value"])) {

                    try {
                        $v = implode(',', $project["value"]);

                        // 包含http，给数组
                        if (strpos($v, 'http') !== false) {
                            $v = $project['value'];
                        }
                    } catch (\Exception $e) {
                        $v = json_encode($project['value'], JSON_UNESCAPED_UNICODE);
                    }

                } else {
                    $v = $project["value"];
                }

                $details[$project['text']] = $v;
            }
        }
        CruiseOrderProcessV2Model::add($this->cruiseOrderModel->id, CruiseOrderModel::STATUS_NOT_SUBMIT,
            CruiseOrderProcessV2Model::TYPE_DEFAULT, '提交', $details);

        DB::commit();

        // 判断是不是自动审核
        // 手动审核
        if ($activityAction->examineSwitch == ActivityModel::SWITCH_ON) {

            $shop             = ShopModel::query()->where('id', $this->cruiseOrderModel->shopId)->first();
            $shopName         = $shop->name ?? '';
            $shopCode         = $shop->shopCode ?? 0;
            $addressPrefix    = $shop->addressPrefix ?? '';

            $activityName       = $activity->name ?? '';
            $activityActionName = $activityAction->name ?? '';

            $submitLastUsername = (new RmsUserApi())->getUserInfoByIds([$this->userId])['data'][0]['username'] ?? '';
            if (strlen($submitLastUsername) > 0) {
                $submitLastUsername = mb_substr($submitLastUsername, 0, 1) . str_repeat('*', mb_strlen($submitLastUsername) - 1);
            }

            $url = \App\Service\OpenShop\Feishu\BaseService::commonWebUrl('/shopOrderActivity/auditDetail?id=' . $join->id . "&isAudit=1");

            // 待审核消息
            $cardMessageBuilder = (new CardMessageBuilder("【待审核】{$shopCode}-{$activityActionName}，审核通知，请及时处理"))
                ->template('orange')
                ->addElement(Tag::divMarkdown("门店名称：{$shopCode}{$shopName}"))
                ->addElement(Tag::divMarkdown("门店区域：{$addressPrefix}"))
                ->addElement(Tag::divMarkdown("申请时间：" . date('Y-m-d H:i:s')))
                ->addElement(Tag::divMarkdown("申请人：{$submitLastUsername}"))
                ->addElement(Tag::divMarkdown("审核状态：待审核"))
                ->addElement(Tag::divMarkdown("活动名称：{$activityName}"))
                ->addElement(Tag::divMarkdown("选项名称：{$activityActionName}"))
                ->addElement(Tag::hr())
                ->addElement(Tag::actions()->addAction(Tag::button()->url($url)->text('立即处理')))
                ->build();

            // 群推送
            $fsConfig = $this->getFsConfig();
            if ($fsConfig) {
                BuildFs::newRobot(0, BuildFs::MSG_TYPE_CARD)
                       ->setCardContent($cardMessageBuilder)
                       ->setRobotConfig($fsConfig['webhook'], $fsConfig['secret'])
                       ->send();
            }

            // 审核人推送
            $users = json_decode($activityAction->examineUser, true);

            $userIds = [];
            foreach ($users as $user) {
                $userIds[] = $user['uid'] ?? 0;
            }

            BuildFs::newRobot('center', BuildFs::MSG_TYPE_CARD, BuildFs::MODULE_TYPE_APP)
                   ->setCardContent($cardMessageBuilder)
                   ->setUserIds($userIds)
                   ->send();
        } else {

            // 自动审核
            $this->cruiseOrderModel->status = CruiseOrderModel::STATUS_COMPLETE;
            $this->cruiseOrderModel->save();
        }

        // cruise_order_change事件
        event(new CruiseOrderChangeEvent($this->cruiseOrderModel->id, $this->templateType, $this->oldCruiseOrderModel,
            $this->cruiseOrderModel));
    }

    /**
     * @param array $data
     */
    public function audit(array $data): void
    {
        // 状态校验
        if (!in_array($this->cruiseOrderModel->status,
            [
                CruiseOrderModel::STATUS_NOT_REVIEW,
                CruiseOrderModel::STATUS_NOT_MODIFY,
            ])) {
            $statusText = CruiseOrderModel::CRUISE_STATUS_MAPPING[$this->cruiseOrderModel->status] ?? '';
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "当前状态: {$statusText}，不允许提交");
        }

        $handler = $this->getCurrentHandlerInfo($this->cruiseOrderModel->status);

        if (!in_array($this->userId, $handler['userIds']) && $handler['userIds'] != [-1]) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null,
                "您无权操作，当前处理人：{$handler['userNames']}");
        }

        DB::beginTransaction();

        if ($data['agree'] == CruiseOrderProcessV2Model::TYPE_AGREE) {
            $this->cruiseOrderModel->status = CruiseOrderModel::STATUS_COMPLETE;
            $details                        = ["通过理由" => $data["reason"]];
            $agreeText                      = '审核通过';
            $agreeColor                     = 'green';
        } else {
            $this->cruiseOrderModel->status = CruiseOrderModel::STATUS_NOT_MODIFY;
            $details                        = ["驳回理由" => $data["reason"]];
            $agreeText                      = '审核驳回';
            $agreeColor                     = 'red';
        }

        $this->cruiseOrderModel->save();

        // 操作日志
        CruiseOrderProcessV2Model::add($this->cruiseOrderModel->id, CruiseOrderModel::STATUS_NOT_REVIEW, $data['agree'],
            $data['reason'], $details);

        DB::commit();

        // event转成同步的
        Config::set('event.connection', 'sync');

        // cruise_order_change事件
        event(new CruiseOrderChangeEvent($this->cruiseOrderModel->id, $this->templateType, $this->oldCruiseOrderModel,
            $this->cruiseOrderModel));

        // 数据准备
        list($activity, $activityAction, $join) = $this->getActivityAndAction();

        $activityId       = $join->activityId ?? 0;

        $activityName       = $activity->name ?? '';
        $activityActionName = $activityAction->name ?? '';
        $shop               = ShopModel::query()->where('id', $this->cruiseOrderModel->shopId)->first();
        $shopName           = $shop->name ?? '';
        $shopCode           = $shop->shopCode ?? 0;
        $addressPrefix      = $shop->addressPrefix ?? '';

        // 最后提交时间
        $submitLast     = $this->cruiseOrderModel
            ->cruiseOrderProcessV2Rel
            ->where('cruiseOrderStatus', CruiseOrderModel::STATUS_NOT_SUBMIT)
            ->sortByDesc('id')
            ->first();
        $submitLastTime     = $submitLast ? strtotime($submitLast['createdAt'] ?? '') : 0;
        $submitLastUid      = $submitLast['createdByUid'] ?? 0;
        $submitLastUser = (new RmsUserApi())->getUserInfoByIds([$submitLastUid])['data'][0] ?? [];
        $submitLastUsername = $submitLastUser['username'] ?? '';

        // 只留第一个字，后面的*
        if (strlen($submitLastUsername) > 1) {
            $submitLastUsername = mb_substr($submitLastUsername, 0, 1) . str_repeat('*', mb_strlen($submitLastUsername) - 1);
        }

        $submitLastMobile = $submitLastUser['mobile'] ?? '';

        $fsConfig = $this->getFsConfig();
        if ($fsConfig) {

            // 审核人
            $fsUser = KmsUser::query()->where('rmsUserId', $this->userId)->first();
            if ($fsUser) {
                $auditName = $fsUser->nickname . '(' . $fsUser->name . ')';
            } else {
                $auditName = '';
            }

            $title = $shopCode . '-' . $activityActionName;

            $webUrl = \App\Service\OpenShop\Feishu\BaseService::commonWebUrl('/shopOrderActivity/auditDetail?id=' . $join->id);

            $cardMessageBuilder = (new CardMessageBuilder("【{$agreeText}】{$title}，审核通知，请注意"))
                ->template($agreeColor)
                ->addElement(Tag::divMarkdown("门店名称：{$shopCode}{$shopName}"))
                ->addElement(Tag::divMarkdown("门店区域：{$addressPrefix}"))
                ->addElement(Tag::divMarkdown("申请时间：" . date('Y-m-d H:i:s', $submitLastTime)))
                ->addElement(Tag::divMarkdown("申请人：{$submitLastUsername}"))
                ->addElement(Tag::divMarkdown("审核状态：{$agreeText}"))
                ->addElement(Tag::divMarkdown("活动名称：{$activityName}"))
                ->addElement(Tag::divMarkdown("选项名称：{$activityActionName}"))
                ->addElement(Tag::divMarkdown("审核人：{$auditName}"))
                ->addElement(Tag::divMarkdown("审核原因：{$data['reason']}"))
                ->addElement(Tag::divMarkdown("审核时间：" . date('Y-m-d H:i:s')))
                ->addElement(Tag::hr())
                ->addElement(Tag::actions()->addAction(Tag::button()->url($webUrl)->text('查看详情')))
                ->build();

            BuildFs::newRobot(0, BuildFs::MSG_TYPE_CARD)
                   ->setCardContent($cardMessageBuilder)
                   ->setRobotConfig($fsConfig['webhook'], $fsConfig['secret'])
                   ->send();
        }

        // 系统消息
        $shopId = $this->cruiseOrderModel->shopId;
        $url    = config('open-shop.m') . "activity/v2?id=" . $activityId;

        if ($data['agree'] == CruiseOrderProcessV2Model::TYPE_AGREE) {

            $notify = SystemNotifyService::save(
                false,
                $title = "门店活动资料审核通过通知",
                SystemNotifyCenterModel::NOTIFY_TYPE_3,
                SystemNotifyCenterModel::NOTIFY_TARGET_1,
                '',
                $title,
                $url,
                SystemNotifyCenterModel::METHOD_TYPE_AUTOMATIC,
                "您在{$shopCode}门店提交的资料：{$activityActionName}【审核已通过】，点击查看详情。",
                '',
                SystemNotifyCenterModel::IS_POPUP_OFF,
                1,
                $shopId
            );

        } else {

            $notify = SystemNotifyService::save(
                false,
                $title = "门店活动资料审核不通过通知",
                SystemNotifyCenterModel::NOTIFY_TYPE_3,
                SystemNotifyCenterModel::NOTIFY_TARGET_1,
                '',
                $title,
                $url,
                SystemNotifyCenterModel::METHOD_TYPE_AUTOMATIC,
                "您在{$shopCode}门店提交的资料：{$activityActionName}【审核不通过】请及时修改，点击查看详情。",
                '',
                SystemNotifyCenterModel::IS_POPUP_OFF,
                1,
                $shopId
            );
        }

        SystemNotifyService::recordLog($notify, '创建消息');
        SystemNotifyService::preSend($notify->id, [$submitLastUid]);

        // 短信
        if ($submitLastMobile) {
            dispatch(function () use ($data, $shopCode, $activityActionName, $submitLastMobile) {

                if ($data['agree'] == CruiseOrderProcessV2Model::TYPE_AGREE) {

                    (new SmsService())->aliyunSend($submitLastMobile, 'SMS_465985243', [
                        "shopCode"   => $shopCode,
                        'actionName' => $activityActionName,
                    ]);

                } else {
                    (new SmsService())->aliyunSend($submitLastMobile, 'SMS_465915257', [
                        "shopCode"   => $shopCode,
                        'actionName' => $activityActionName,
                    ]);
                }
            });
        }
    }

    /**
     * 获取阶段对应处理人
     * @param int $status
     * @return array
     * @throws GuzzleException
     */
    public function getCurrentHandlerInfo(int $status): array
    {
        switch ($status) {
            case CruiseOrderModel::STATUS_NOT_SUBMIT:
            case CruiseOrderModel::STATUS_NOT_MODIFY:
            case CruiseOrderModel::STATUS_CLOSED:

//                $users = RmsCurl::getIns()
//                                ->do('api/internal/user/usersInShop', ['shopId' => $this->cruiseOrderModel->shopId],
//                                    'GET')['data'] ?? [];

                // 门店权限人员
                $arr = [
                    'userIds'   => [-1],
                    'userNames' => '',
                ];

                break;
            case CruiseOrderModel::STATUS_NOT_REVIEW:
            case CruiseOrderModel::STATUS_COMPLETE:

                $join = ActivityShopJoinModel::query()
                                             ->where('orderNo', $this->cruiseOrderModel->id)
                                             ->first();
                if (!$join) {
                    BaseService::throwErr("找不到项目动作对应的表单信息：{$this->cruiseOrderModel->id}");
                }

                $actionId       = $join->activityActionId ?? 0;
                $activityAction = ActivityActionModel::query()->find($actionId);
                if (!$activityAction) {
                    BaseService::throwErr("找不到项目动作信息：{$actionId}");
                }

                $userIds   = [];
                $userNames = '';

                // 需要审核
                if ($activityAction->examineSwitch == ActivityModel::SWITCH_ON) {
                    $users = json_decode($activityAction->examineUser, true);

                    foreach ($users as $user) {
                        $userIds[] = $user['uid'] ?? 0;
                        $userNames .= ($user['username'] ?? '') . ',';
                    }
                    $userNames = rtrim($userNames, ',');
                } else {
                    $userIds   = [-1];
                    $userNames = '无需审批';
                }

                // 总部负责人
                $arr = [
                    'userIds'   => $userIds,
                    'userNames' => $userNames,
                ];

                break;

            default:
                return [
                    'userIds'   => [],
                    'userNames' => '',
                ];
        }


        return $arr;
    }

    /**
     * 获取机器人配置
     * @return array
     */
    private function getFsConfig(): array
    {
        // 飞书机器人配置
        $activityActionId = ActivityShopJoinModel::query()
                                                 ->where('orderNo', $this->cruiseOrderModel->id)
                                                 ->value('activityActionId');

        if (!$activityActionId) {
            return [];
        }

        $activityAction = ActivityActionModel::query()->find($activityActionId);
        if (!$activityAction) {
            return [];
        }
        $webhook = $activityAction->groupNotificationBotWebhook ?? '';
        $secret  = $activityAction->groupNotificationBotSecret ?? '';

        if (!$webhook || !$secret) {
            return [];
        }

        return [
            'webhook' => $webhook,
            'secret'  => $secret,
        ];
    }

    /**
     * 获取活动和动作
     * @return array
     */
    private function getActivityAndAction(): array
    {
        $join = ActivityShopJoinModel::query()
                                     ->where('orderNo', $this->cruiseOrderModel->id)
                                     ->first();

        if (!$join) {
            return [null, null, null];
        }

        $activityId       = $join->activityId ?? 0;
        $activityActionId = $join->activityActionId ?? 0;

        $activity       = ActivityModel::query()->where('id', $activityId)->first();
        $activityAction = ActivityActionModel::query()->where('id', $activityActionId)->first();

        return [$activity, $activityAction, $join];
    }
}
